AOP – Implementing Role Based Security
You may want to implement role-based security, where you only allow users assigned a certain role to perform certain actions in an application. Many different classes in your code will need role-based security added to them. As it turns out, role-based security is a cross-cutting concern. Well, Aspect Oriented Programming (AOP) can help you modular such a role-based security structure.
Lets start with an example. Maybe you have a database filled with people (people being a list of user or person objects). You want to control the list of people. Now think of the Create, Read, Update, Delete (CRUD) pattern. Now turn those into four permissions. Any role could potentially have or not have rights to create a person, read a person’s info, update a person’s info, or delete a person. An admin user would likely have all of the four CRUD rights. A user would likely have CRUD rights for their own user, but just read rights for other users. Your design might have multiple levels of rights as well. You may want to provide multiple levels of read permissions. Think of any social network where you have more read rights if you are a friend of another Person.
If it was just for a Person object, you probably would implement an AOP-based solution. However, a large application will have dozens of classes around the Person class. It will have many entities besides Person and those entities have many surrounding data classes as well. What if you had to add code to over 100 class objects? Now you can really benefit from an AOP-based design.
Well, I am going to show you example to help get you started.
Lets say you want to encrypt a field of a class. You might think that this is not a crosscutting concern, but it is. What if throughout and entire solution you need to encrypt random fields in many of your classes. Adding encryption to each of the classes can be a significant burden and breaks the “single responsibility principle” by having many classes implementing encryption. Of course, a static method or a single might be used to help, but even with that, code is must be added to each class. With Aspect Oriented Programming, this encryption could happen in one Aspect file, and be nice and modular.
Prereqs
This example assumes you have a development environment installed with at least the following:
- JDK
- AspectJ
- Eclipse (Netbeans would work too)
Step 1 – Create an AspectJ project
- In Eclipse, choose File | New | Project.
- Select AspectJ | AspectJ Project.
- Click Next.
- Name your project.
Note: I named my project AOPRolePermissions - Click Finish.
Step 2 – Create a class containing main()
- Right-click on the project in Package Explorer and choose New | Class.
- Provide a package name.
Note: I named my package the same as the project name. - Give the class a name.
Note: I often name my class Main. - Check the box to include a public static void main(String[] args) method.
- Click Finish.
package AOPRolePermissions; public class Main { public static void main(String[] args) { // TODO Auto-generated method stub } }
Step 3 – Create an object that needs Role-based security
For this example, I am going to use a simple Person object.
- Right-click on the package in Package Explorer and choose New | Class.
Note: The package should already be filled out for you. - Give the class a name.
Note: I named mine Person. - Click Finish.
- Add String fields for FirstName and LastName.
- Add a getter and setter for each.
package AOPRolePermissions; public class Person { // First Name private String FirstName = ""; public String getFirstName() { return FirstName; } public void setFirstName(String inFirstName) { FirstName = inFirstName; } // Last Name private String LastName = ""; public String getLastName() { return LastName; } public void setLastName(String inLastName) { LastName = inLastName; } }
a
Step 4 – Implement example role-based code
For this I created the following objects:
- Role
- Permission
- Permissions
- FakeSession
The implementation of these is not important to this article, so I am not posting their code. However, you will see these classes if you download the project.
Step 5 – Implement an Annotation for Role-based Security
Lets add an annotation to mark methods that should use role-based security.
- Right-click on the package in Package Explorer and choose New | Annotation.
Note: The package should already be filled out for you. - Give the annotation a name.
Note: I named mine RoleBasedSecurity. - Click Finish.
- Add a value for the permission type.
- Add a value for the Field name (in case the method is named completely different from the field).
- Set the Retention to RetentionPolicy.RUNTIME.
- Maybe add a comment that this annotation is for use by the Aspect (which we will create shortly).
package AOPRolePermissions; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @Retention(RetentionPolicy.RUNTIME) public @interface RoleBasedSecurity { Permission.Type value() default Permission.Type.All; String FieldName() default ""; }
Step 6 – Add the @RoleBasedSecurity annotation to methods
- In the Person class, add @RoleBasedSecurity(Type.Read) tag above the gettersof Person.
- In the Person class, add @RoleBasedSecurity(Type.Update) tag above the setters of Person.
package AOPRolePermissions; import AOPRolePermissions.Permission.Type; public class Person { // First Name private String FirstName = ""; @RoleBasedSecurity(value = Type.Read) public String getFirstName() { return FirstName; } @RoleBasedSecurity(Type.Update) public void setFirstName(String inFirstName) { FirstName = inFirstName; } // Last Name private String LastName = ""; @RoleBasedSecurity(value = Type.Read) public String getLastName() { return LastName; } @RoleBasedSecurity(Type.Update) public void setLastName(String inLastName) { LastName = inLastName; } }
Step 7 – Create an Aspect to check Role-based permissions
- Right-click on the package in Package Explorer and choose New | Other.
- Choose AspectJ | Aspect.
- Click Next.
Note: The package should already be filled out for you. - Give the Aspect a name.
Note: I named mine SecureByRoleAspect. - Click Finish.
package AOPRolePermissions; public aspect SecureByRoleAspect { }
Step 7 – Add the pointcut and advice
- Add a pointcut called RoleBasedSecurityMethod.
- Implement it to work for any method called that is annotated with @RoleBasedSecurity: call(@RoleBasedSecurity * *(..)).
- Add a !within(SecureByRoleAspect) (to prevent an infinite loop).
package AOPEncryptionExample; public aspect EncryptFieldAspect { pointcut RoleBasedSecurityMethod() : call(@RoleBasedSecurity * *(..)) && !within(SecureByRoleAspect); }
You now have your pointcut.
Step 8 – Implement around advice to check for permissions
- Add around advice that returns an Object.
- Implement it to be for the RoleBasedSecurityMethod pointcut.
- Add code to check for permissions.
- Add a return statement.
package AOPRolePermissions; import java.lang.reflect.Method; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.Signature; import org.aspectj.lang.reflect.MethodSignature; public aspect SecureByRoleAspect { pointcut RoleBasedSecurityMethod() : call(@RoleBasedSecurity * *(..)) && !within(SecureByRoleAspect); Object around() : RoleBasedSecurityMethod() { System.out.println("Checking permissions..."); RoleBasedSecurity rbs = getRBSAnnotation(thisJoinPointStaticPart); // Use the FieldName if specified, otherwise guess it from the method name String field = (rbs.FieldName().equals("")) ? removeLowerCasePrefix(thisJoinPointStaticPart .getSignature().getName()) : rbs.FieldName(); if (FakeSession.Instance.getCurrentRole().GetPermissions() .can(rbs.value(), field)) { System.out.println(String.format( "Success: Role has permissions to %s field named %s.%s.", rbs.value(), thisJoinPointStaticPart.getSignature() .getDeclaringType().getName(), field)); return proceed(); } else { System.out .println(String .format("Failure: Role has insufficient permissions to %s field named %s.%s.", rbs.value(), thisJoinPointStaticPart .getSignature().getDeclaringType() .getName(), field)); } return null; } private String removeLowerCasePrefix(String inString) { int startPoint = 0; for (int i = 0; i < inString.length(); i++) { if (Character.isUpperCase(inString.charAt(i))) { startPoint = i; break; } } return inString.substring(startPoint); } private RoleBasedSecurity getRBSAnnotation(JoinPoint.StaticPart inStaticPart) { RoleBasedSecurity rbs = null; Signature sig = inStaticPart.getSignature(); if (sig instanceof MethodSignature) { // this must be a call or execution join point Method method = ((MethodSignature) sig).getMethod(); rbs = method.getAnnotation(RoleBasedSecurity.class); } return rbs; } }
You are done. Go ahead and run the program. You should get the following output.
Checking permissions... Success: Role has permissions to Update field named AOPRolePermissions.Person.FirstName. Checking permissions... Success: Role has permissions to Update field named AOPRolePermissions.Person.LastName. Checking permissions... Success: Role has permissions to Read field named AOPRolePermissions.Person.FirstName. John Checking permissions... Success: Role has permissions to Read field named AOPRolePermissions.Person.LastName. Johnson Checking permissions... Failure: Role has insufficient permissions to Update field named AOPRolePermissions.Person.FirstName. Checking permissions... Failure: Role has insufficient permissions to Update field named AOPRolePermissions.Person.LastName. Checking permissions... Success: Role has permissions to Read field named AOPRolePermissions.Person.FirstName. John Checking permissions... Success: Role has permissions to Read field named AOPRolePermissions.Person.LastName. Johnson
Role Based Security with AOP Project Download
Return to Aspected Oriented Programming – Examples
[...] – Implementing Role Based Security Filed under: FreeBSD — rhyous @ 12:31 am Read more Share this:DiggRedditLike this:LikeBe the first to like this post. Leave a [...]